﻿#include "ngx_c_conf.h"
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <vector>
#include "ngx_global.h"
#include "ngx_func.h"

// 配置类静态实例初始化位空
CConfig* CConfig::m_instance = NULL;

CConfig::CConfig()
{

}

CConfig::~CConfig()
{
    std::vector<LPCConfItem>::iterator iter;
    for (iter = m_configItemList.begin(); iter != m_configItemList.end(); ++iter)
    {
        delete *iter;
    }
    m_configItemList.clear();
}

bool CConfig::Load(const char* pConfigName)
{
    FILE* fp = fopen(pConfigName, "r");
    if (fp == NULL)
    {
        return false;
    }

    // 每一行的配置文件读取出来都在这里
    char linebuf[512] = { 0 };

    while (!feof(fp))
    {
        if (fgets(linebuf, 511, fp) == NULL)
        {// 读取到结尾
            continue;   
        }
        if (linebuf[0] == 0)
        {// 读取到的第一个字符是字符串结尾标志(\0)
            continue;
        }
        if (*linebuf == ';' || *linebuf == ' ' || *linebuf == '#' || *linebuf == '\t' || *linebuf == '\n' || *linebuf == '[')
        {// 如果读取的第一个字符是; 空格 # \t \n 直接掠过
            continue;
        }
    // 切除尾部多余字符的循环标签，用goto回到这里
    processsubstring:
        int nLen = strlen(linebuf);
        if (nLen > 0)
        {// 如果这一行经过处理后还有字符的话
            // 在这一行尾部 换行 回车 或者 空格 等都要截掉
            if (linebuf[nLen - 1] == 10 || linebuf[nLen - 1] == 13 || linebuf[nLen - 1] == 32)
            {
                linebuf[nLen - 1] = 0;
                goto processsubstring;
            }
            if (linebuf[0] == 0)
            {// 经过处理后变成了空行
                continue;
            }
            if (linebuf[0] == '[')
            {// 配置组信息也不处理
                continue;
            }

            // 找出=分割字符串
            char* ptemp = strchr(linebuf, '=');
            if (ptemp != NULL)
            {// 找到了=的配置行才算作有效
                LPCConfItem pConfItem = new CConfItem;
                memset(pConfItem, 0, sizeof(CConfItem));
                // 将等号左边的拷贝到配置项名(右边的减法是用等号的地址减去行配置的第一个的地址)
                strncpy(pConfItem->ItemName, linebuf, (int)(ptemp - linebuf));
                // 将等号右边的拷贝到配置项内容
                strcpy(pConfItem->ItemContent, ptemp + 1);

                // 切掉所有的空格
                Ltrim(pConfItem->ItemName);
                Rtrim(pConfItem->ItemName);
                Ltrim(pConfItem->ItemContent);
                Rtrim(pConfItem->ItemContent);

                m_configItemList.push_back(pConfItem);
            }
        }
    }
    fclose(fp);
    return true;
}

char* CConfig::GetString(const char* pItemName)
{
    std::vector<LPCConfItem>::iterator iter;
    for (iter = m_configItemList.begin(); iter != m_configItemList.end(); ++iter)
    {
        if (strcasecmp((*iter)->ItemName, pItemName) == 0)
        {
            return (*iter)->ItemContent;
        }
    }
    return NULL;
}

int CConfig::GetIntDefault(const char* pItemName, const int def)
{
    std::vector<LPCConfItem>::iterator iter;
    for (iter = m_configItemList.begin(); iter != m_configItemList.end(); ++iter)
    {
        if (strcasecmp((*iter)->ItemName, pItemName) == 0)
        {
            return atoi((*iter)->ItemContent);
        }
    }
    return def;
}

void CConfig::show()
{
    std::vector<LPCConfItem>::iterator iter;
    printf("test print config item begin=====\n");
    for (iter = m_configItemList.begin(); iter != m_configItemList.end(); ++iter)
    {
        printf("#%s# : #%s#\n", (*iter)->ItemName, (*iter)->ItemContent);
    }
    printf("test print config item end=====\n");
}
